package org.geometerplus.android.fbreader.util;

import android.text.TextUtils;
import android.util.Log;

import org.geometerplus.android.fbreader.util.rxjava.CommonRxTask;
import org.geometerplus.android.fbreader.util.rxjava.RxjavaUtil;
import org.geometerplus.zlibrary.text.model.ZLTextModel;

import io.reactivex.disposables.Disposable;

public class BookSearch {

    private Disposable disposable;

    public interface BookSearchCallback {

        void onFinishWithResult();

        void onFinishNoResult();

        void onError(String msg);

        void onCanceled();
    }

    @SuppressWarnings("unused")
    private static final String TAG = BookSearch.class.getSimpleName();

    // true if we want to cancel booksearch
    boolean mCancel = false;

    // true if the booksearch thread should exit
    boolean mRuning;

    // true if ignore case
    boolean mIgnoreCase;

    // true if search the whole book
    boolean mWholeSearch;

    // true if search backward
    boolean mBackWard;

    ZLTextModel mModel;

    private static BookSearch INSTANCE = null;

    public static BookSearch getInstance() {
        if (INSTANCE == null)
            INSTANCE = new BookSearch();

        return INSTANCE;
    }

    private BookSearch() {
    }

    public synchronized void search(final ZLTextModel model, final String text, final BookSearchCallback callback) {
        if (isRuning())
            return;

        disposable = RxjavaUtil.executeTask(new CommonRxTask() {
            @Override
            public void doInIOThread() {
                executeSearch(model, text, callback);
            }
        });
    }

    public void cancel() {
        mCancel = true;
        mRuning = false;
        try {
            if (disposable != null)
                disposable.dispose();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void executeSearch(ZLTextModel model, String text, BookSearchCallback callback) {
        Log.d(TAG, "executeSearch: ");
        if (model == null || TextUtils.isEmpty(text)) {
            String msg = "搜索失败: model为空或者关键字为空";
            L.d(msg);
            callback.onFinishNoResult();
            return;
        }

        reset();

        mRuning = true;
        mModel = model;

        int startIndex = 0;
        int endIndex = mModel.getParagraphsNumber();

        int count;

        try {
            count = mModel.search(text, startIndex, endIndex, mIgnoreCase);

            Log.d(TAG, "executeSearch count: " + count);
            if (callback != null) {
                if (count == 0) {
                    callback.onFinishNoResult();
                } else {
                    callback.onFinishWithResult();
                }
            }

            mRuning = false;
        } catch (Exception e) {
            L.e(TAG, "search error: " + e.toString());
            if (callback != null)
                callback.onError(e.getCause() != null ? e.getCause().toString() : e.getMessage());
        }
    }

    public void reset() {
        mModel = null;
        mRuning = false;
        mCancel = false;
    }

    public boolean isRuning() {
        return mRuning;
    }
}
